<?php
declare(strict_types=1);

namespace Core\Package\ElementPlus\FormCreate\FormItem;

use Core\Basics\BasicsServe;
use Core\Exception\PrintException;
use Hyperf\Database\Model\Builder;
use JetBrains\PhpStorm\ExpectedValues;
use Zms\Unit\Is;

class SearchPanel extends FormItemAbstract
{
    protected string $_type = 'search-panel';

    private string $valueType = self::VALUE_TYPE_STRING;

    /**
     * 获取值类型
     * @return string
     */
    public function valueType(): string
    {
        return $this->valueType;
    }

    protected function defaultProps(): array
    {
        return [
            'search' => [],
            'buttonName' => '选择',
            'selected' => [],
            'valueKey' => 'id',
            'labelKey' => 'name',
            'simple' => true
        ];
    }

    /**
     * Radio constructor.
     * @param string $field
     * @param string $title
     * @param string $api 请求地址
     * @param string|array|int $value
     */
    public function __construct(string $field, string $title, string $api, string|array|int $value = '')
    {
        $this->_title = $title;
        $this->_field = $field;
        $this->_value = $value;
        if (is_numeric($value)) {
            $this->setValueType(self::VALUE_TYPE_NUMBER);
        } elseif (is_string($value)) {
            $this->setValueType(self::VALUE_TYPE_STRING);
        } elseif (is_array($value)) {
            $this->setValueType(self::VALUE_TYPE_ARRAY);
        }
        $this->api($api);
        $this->title("{$title}搜索");
        $this->placeholder("请选择{$title}");
    }

    /**
     * 标题设置
     * @param int $title
     * @return SearchPanel
     */
    public function title(string $title): SearchPanel
    {
        return $this->props('title', $title);
    }

    /**
     * 组件提示
     * @param string $placeholder
     * @return SearchPanel
     */
    public function placeholder(string $placeholder): SearchPanel
    {
        return $this->props('placeholder', $placeholder);
    }


    /**
     * 设置可选数量
     * @param int $limit
     * @return SearchPanel
     */
    public function limit(int $limit): SearchPanel
    {
        return $this->props('limit', $limit);
    }


    /**
     * 搜索面板宽度
     * @param int|string $width
     * @return SearchPanel
     */
    public function width(int|string $width): SearchPanel
    {
        return is_numeric($width) ? $this->props('width', "{$width}px") : $this->props('width', $width);
    }


    /**
     * 简洁模式
     * @param bool $simple
     * @return SearchPanel
     */
    public function simple(bool $simple): SearchPanel
    {
        return $this->props('simple', $simple);
    }


    /**
     * 设置数据列
     * [ ['key'=>'id','label'=>'ID'] ]
     * @param array $column
     * @return SearchPanel
     */
    public function columns(array $column): SearchPanel
    {
        return $this->props('columns', $column);
    }

    /**
     * 设置API
     * @param string $api
     * @return SearchPanel
     */
    public function api(string $api): SearchPanel
    {
        return $this->props('api', $api);
    }


    /**
     * 默认筛选条件
     * @param array $query
     * @return SearchPanel
     */
    public function query(array $query): SearchPanel
    {
        return $this->props('query', $query);
    }

    /**
     * 按钮名称
     * @param string $buttonName
     * @return SearchPanel
     */
    public function buttonName(string $buttonName): SearchPanel
    {
        return $this->props('buttonName', $buttonName);
    }

    /**
     * 已选数据
     * @param array|string|BasicsServe $selected
     * @return SearchPanel
     * @throws PrintException
     */
    public function selected(array|string|BasicsServe $selected): SearchPanel
    {
        if (is_array($selected)) {
            return $this->props('selected', $selected);
        } elseif (Is::empty($this->_value)) {
            return $this->props('selected', []);
        }
        $props = $this->getProps();
        if (gettype($selected) === 'string') {
            $result = (new $selected)->newQuery()
                ->when(Is::notEmpty($this->_value), function (Builder $query) use ($props) {
                    if (is_array($this->_value)) {
                        $query->whereIn($props['valueKey'], $this->_value);
                    } else {
                        $query->where($props['valueKey'], $this->_value);
                    }
                })
                ->select(["{$props['valueKey']} as value", "{$props['labelKey']} as label"])
                ->get()
                ->toArray();
            return $this->props('selected', $result);
        } elseif ($selected instanceof BasicsServe) {
            $result = $selected->search()
                ->when(Is::notEmpty($this->_value), function (Builder $query) use ($props) {
                    if (is_array($this->_value)) {
                        $query->whereIn($props['valueKey'], $this->_value);
                    } else {
                        $query->where($props['valueKey'], $this->_value);
                    }
                })
                ->select(["{$props['valueKey']} as value", "{$props['labelKey']} as label"])
                ->get()
                ->toArray();
            return $this->props('selected', $result);
        }
        return $this->props('selected', []);
    }


    /**
     * 值属性名
     * @param string $valueKey
     * @return SearchPanel
     */
    public function valueKey(string $valueKey): SearchPanel
    {
        return $this->props('valueKey', $valueKey);
    }


    /**
     * 名称属性名
     * @param string $labelKey
     * @return SearchPanel
     */
    public function labelKey(string $labelKey): SearchPanel
    {
        return $this->props('labelKey', $labelKey);
    }


    /**
     * 是否多选
     * @param bool $multiple
     * @return SearchPanel
     */
    public function multiple(bool $multiple): SearchPanel
    {
        if ($multiple === true) {
            $this->valueType = self::VALUE_TYPE_ARRAY;
        } else {
            $this->valueType = self::VALUE_TYPE_STRING;
        }
        return $this->props('multiple', $multiple);
    }


    /**
     * 设置数据类型
     * @param string $valueType
     * @return SearchPanel
     */
    public function setValueType(#[ExpectedValues([self::VALUE_TYPE_STRING, self::VALUE_TYPE_ARRAY, self::VALUE_TYPE_NUMBER])] string $valueType): SearchPanel
    {
        $this->valueType = $valueType;
        return $this;
    }
}